package com.mavenq.fly.aspect;

import com.alibaba.fastjson.JSON;
import com.mavenq.fly.annotation.Log;
import com.mavenq.fly.business.entity.OperationLog;
import com.mavenq.fly.business.service.LogService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

@Aspect
@Component
public class LogAspect {
    @Autowired
    private LogService logService;

    @Pointcut("@annotation(com.mavenq.fly.annotation.Log)")
    public void logPointCut() {}

    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Log logAnnotation = method.getAnnotation(Log.class);

        OperationLog operationLog = new OperationLog();
        operationLog.setTitle(truncateString(logAnnotation.title(), 100));
        operationLog.setOperation(truncateString(logAnnotation.operation(), 100));
        operationLog.setMethod(truncateString(
            joinPoint.getTarget().getClass().getName() + "." + method.getName(),
            200));
        operationLog.setOperationTime(new Date());
        operationLog.setIp(truncateString(getIpAddress(request), 50));

        long startTime = System.currentTimeMillis();
        Object result = null;

        try {
            if (logAnnotation.saveParams()) {
                try {
                    String params = logService.prettyJson(joinPoint.getArgs());
                    params = logService.filterSensitiveInfo(params);
                    operationLog.setParams(truncateString(params, logAnnotation.maxParamLength()));
                } catch (Exception e) {
                    operationLog.setParams("参数序列化失败: " + e.getMessage());
                }
            }

            result = joinPoint.proceed();
            operationLog.setStatus(0);

            if (logAnnotation.saveResult()) {
                try {
                    String jsonResult = logService.prettyJson(result);
                    jsonResult = logService.filterSensitiveInfo(jsonResult);
                    operationLog.setResult(truncateString(jsonResult, logAnnotation.maxResultLength()));
                } catch (Exception e) {
                    operationLog.setResult("结果序列化失败: " + e.getMessage());
                }
            }
        } catch (Exception e) {
            operationLog.setStatus(1);
            String errorMsg = e.getMessage() != null ? e.getMessage() : e.toString();
            operationLog.setErrorMsg(truncateString(errorMsg, logAnnotation.maxErrorLength()));
            throw e;
        } finally {
            operationLog.setExecutionTime(System.currentTimeMillis() - startTime);
            logService.saveLog(operationLog);
        }

        return result;
    }

    private String truncateString(String input, int maxLength) {
        if (input == null) return null;
        return input.length() <= maxLength ? input : input.substring(0, maxLength - 3) + "...";
    }

    private String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip.split(",")[0];
    }
}